
#ifdef CONFIG_USE_WEBSOCKET_DAP // 如果配置了WebSocket DAP

/**
 * Copyright (c) 2021 windowsair <msdn_02 at sina.com>
 * 版权声明：允许自由使用、修改和分发本软件
 */
#include <stdint.h>    // 标准整数类型头文件
#include <string.h>    // 字符串操作函数头文件
#include <sys/param.h> // 系统参数定义头文件（包含min/max等宏）

// 共享头文件

#include "esp_log.h" // ESP32日志功能头文件

#include "freertos/FreeRTOS.h" // FreeRTOS实时操作系统头文件
#include "freertos/task.h"     // FreeRTOS任务管理头文件

#include "mbedtls/base64.h" // mbedTLS Base64编解码头文件
#include "mbedtls/sha1.h"   // mbedTLS SHA1哈希算法头文件

#include "esp_partition.h" // ESP32分区操作头文件
#include "esp_system.h"    // ESP32系统功能头文件

#include "lwip/err.h"     // LwIP错误处理头文件
#include "lwip/sockets.h" // LwIP套接字接口头文件
#include "lwip/sys.h"     // LwIP系统功能头文件
#include <lwip/netdb.h>   // LwIP网络数据库操作头文件

#include "sdkconfig.h" // ESP-IDF项目配置头文件
#include <esp_ota_ops.h> // 正确的引用方式
#include "esp_partition.h"
#include "esp_system.h"

static const char *CO_TAG = "corsacOTA"; // 定义日志标签

// 配置常量
#define CONFIG_CO_SOCKET_BUFFER_SIZE  1500 // 套接字缓冲区大小
#define CONFIG_CO_WS_TEXT_BUFFER_SIZE 100  // WebSocket文本缓冲区大小

// 日志格式宏
#define LOG_FMT(x) "%s: " x, __func__

// 最小值宏
#define min(a, b) ((a) < (b) ? (a) : (b))

// 函数属性宏
#define CO_NO_RETURN __attribute__((noreturn))      // 标记函数无返回值
#define CO_INLINE    __attribute__((always_inline)) // 强制内联函数

// 测试模式开关
#define CO_TEST_MODE 0

#if (CO_TEST_MODE == 1)
#warning corsacOTA test mode is in use  // 测试模式编译警告
#endif

// 外部函数声明
extern void free_dap_ringbuf();                                                // 声明释放DAP环形缓冲区的外部函数
extern uint32_t DAP_ExecuteCommand(const uint8_t *request, uint8_t *response); // 声明执行DAP命令的外部函数

// 函数声明
static void co_websocket_process_dap(uint8_t *data, size_t len); // 处理DAP数据的函数声明

uint8_t *ws_process_buffer = NULL; // WebSocket处理缓冲区指针

#define co_err_t int // 错误类型定义
#define CO_OK    ESP_OK // 错误类型定义
#define CO_FAIL  ESP_FAIL // 错误类型定义

/**
 * @brief corsacOTA websocket 控制块结构体
 */
typedef struct co_websocket_cb {
    uint8_t FIN;    // 帧结束标志位
    uint8_t OPCODE; // 操作码（文本/二进制/关闭等）

    uint8_t MASK;            // 掩码标志位
    size_t payload_len;      // 有效载荷长度（包含扩展长度）
    size_t payload_read_len; // 已读取的有效载荷长度

    union {
        uint32_t val;    // 掩码值（32位整型）
        uint8_t data[4]; // 掩码字节数组
    } mask;

    bool skip_frame; // 是否跳过超长文本帧的标志
} co_websocket_cb_t;

/**
 * @brief corsacOTA 套接字控制块结构体
 */
typedef struct co_socket_cb {
    int fd; // 套接字文件描述符
    enum co_socket_status {
        CO_SOCKET_ACCEPT = 0,              // 等待接受连接状态
        CO_SOCKET_HANDSHAKE,               // WebSocket握手阶段
        CO_SOCKET_WEBSOCKET_HEADER,        // 读取WebSocket帧头
        CO_SOCKET_WEBSOCKET_EXTEND_LENGTH, // 读取扩展长度
        CO_SOCKET_WEBSOCKET_MASK,          // 读取掩码
        CO_SOCKET_WEBSOCKET_PAYLOAD,       // 读取有效载荷
        CO_SOCKET_CLOSING                  // 等待关闭状态
    } status;                              // 套接字当前状态

    char *buf;            // 原始套接字数据缓冲区指针
    size_t remaining_len; // 缓冲区中剩余可用字节数
    size_t read_len;      // 已处理的字节数

    co_websocket_cb_t wcb; // WebSocket控制块
} co_socket_cb_t;

/**
 * @brief corsacOTA OTA 控制块结构体
 */
typedef struct co_ota_cb {
    enum co_ota_status {
        CO_OTA_INIT = 0,    // 初始化状态
        CO_OTA_LOAD,        // 加载中状态
        CO_OTA_DONE,        // 完成状态
        CO_OTA_STOP,        // 停止状态
        CO_OTA_ERROR,       // 错误状态
        CO_OTA_FATAL_ERROR, // 致命错误状态
    } status;               // OTA当前状态
    int32_t error_code;     // 错误代码（待实现）

    const esp_partition_t *update_ptn;  // 指向更新分区的指针
    const esp_partition_t *running_ptn; // 指向运行分区的指针
    esp_ota_handle_t update_handle;     // OTA更新句柄

    int32_t total_size;        // 固件总大小
    int32_t offset;            // 当前处理位置
    int32_t chunk_size;        // 响应分块大小
    int32_t last_index_offset; // 上次响应记录的偏移量
} co_ota_cb_t;

/**
 * @brief corsacOTA HTTP 控制块结构体
 */
typedef struct co_cb {
    int listen_fd;        // 监听套接字文件描述符
    int websocket_fd;     // WebSocket连接文件描述符（只允许一个）
    uint8_t *recv_data;   // WebSocket文本模式接收缓冲区
    int recv_data_offset; // 文本模式接收偏移量
    int max_listen_num;   // 最大连接数（实际只服务一个连接）

    int wait_timeout_sec;  // 超时时间（秒）
    int wait_timeout_usec; // 超时时间（微秒）

    co_socket_cb_t **socket_list; // 套接字控制块列表指针
    co_socket_cb_t *websocket;    // 指向有效的WebSocket连接

    int accept_num;  // 当前已建立连接数
    int closing_num; // 正在关闭的连接数

    co_ota_cb_t ota; // OTA控制块
} co_cb_t;

static co_cb_t *global_cb = NULL; // 全局控制块指针

/* WebSocket 协议帧格式定义（RFC 6455） */
#define WS_FIN                 0x80 // 结束帧标志位掩码
#define WS_RSV1                0x40 // 保留位1掩码
#define WS_RSV2                0x20 // 保留位2掩码
#define WS_RSV3                0x10 // 保留位3掩码
#define WS_OPCODE_CONTINUTAION 0x00 // 延续帧操作码
#define WS_OPCODE_TEXT         0x01 // 文本帧操作码
#define WS_OPCODE_BINARY       0x02 // 二进制帧操作码
#define WS_OPCODE_CLOSE        0x08 // 关闭帧操作码
#define WS_OPCODE_PING         0x09 // Ping帧操作码
#define WS_OPCODE_PONG         0x0A // Pong帧操作码

#define WS_MASK 0x80 // 掩码标志位掩码

// 计算响应帧头偏移量（考虑扩展长度）
static inline int co_websocket_get_res_payload_offset(int payload_len)
{
    return 2 + (payload_len >= 126 ? 2 : 0); // 基础2字节 + 扩展长度2字节（如果需要）
}

// 处理WebSocket帧头
static co_err_t co_websocket_process_header(co_cb_t *cb, co_socket_cb_t *scb)
{
    uint8_t opcode, fin, mask;
    uint64_t payload_len;
    uint8_t *data;

    data = (uint8_t *)scb->buf; // 获取缓冲区数据指针

    // 状态：读取基础帧头
    if (scb->status == CO_SOCKET_WEBSOCKET_HEADER) {
        if (scb->remaining_len < 2)
            return CO_OK; // 数据不足，等待更多数据

        // 检查保留位（必须为0）
        if (data[0] & 0b1110000)
            return CO_FAIL; // 保留位非0，协议错误

        // 解析第一字节
        fin = (data[0] & WS_FIN) == WS_FIN; // 提取结束帧标志
        opcode = data[0] & 0b1111;          // 提取操作码
        // 解析第二字节
        mask = (data[1] & WS_MASK) == WS_MASK; // 提取掩码标志
        payload_len = data[1] & 0x7F;          // 提取基础载荷长度

        // 操作码类型检查
        switch (opcode) {
            case WS_OPCODE_CONTINUTAION:
                break;                    // 延续帧，不做特殊处理
            case WS_OPCODE_TEXT:          // 文本帧
            case WS_OPCODE_BINARY:        // 二进制帧
                scb->wcb.OPCODE = opcode; // 记录操作码
                break;
            case WS_OPCODE_PING:  // Ping帧
            case WS_OPCODE_PONG:  // Pong帧
            case WS_OPCODE_CLOSE: // 关闭帧
                scb->wcb.OPCODE = opcode;
                break;
            default:
                return CO_FAIL; // 不支持的操作码
        }

        // 记录帧信息
        scb->wcb.FIN = fin;
        scb->wcb.MASK = mask;
        scb->wcb.payload_len = payload_len;

        // 处理扩展长度
        if (payload_len == 126 || payload_len == 127) {
            scb->status = CO_SOCKET_WEBSOCKET_EXTEND_LENGTH; // 需要读取扩展长度
        } else if (mask == 1) {
            scb->status = CO_SOCKET_WEBSOCKET_MASK; // 需要读取掩码
        }

        scb->read_len = 2; // 已处理2字节头
    }

    // 状态：读取扩展长度
    if (scb->status == CO_SOCKET_WEBSOCKET_EXTEND_LENGTH) {
        if (scb->wcb.payload_len == 126) { // 2字节扩展长度
            if (scb->remaining_len < scb->read_len + 2)
                return CO_OK;                     // 数据不足
            payload_len = data[2] << 8 | data[3]; // 组合16位长度
            scb->read_len += 2;
        } else if (scb->wcb.payload_len == 127) { // 8字节扩展长度
            if (scb->remaining_len < scb->read_len + 8)
                return CO_OK; // 数据不足
            // 组合64位长度（小端序）
            payload_len = ((uint64_t)(data[9]) << 0) |
                          ((uint64_t)(data[8]) << 8) |
                          ((uint64_t)(data[7]) << 16) |
                          ((uint64_t)(data[6]) << 24) |
                          ((uint64_t)(data[5]) << 32) |
                          ((uint64_t)(data[4]) << 40) |
                          ((uint64_t)(data[3]) << 48) |
                          ((uint64_t)(data[2]) << 56);
            // 最高位必须为0
            if ((payload_len >> 63) & 0b1)
                return CO_FAIL; // 长度非法
            scb->read_len += 8;
        } else {
            payload_len = scb->wcb.payload_len; // 使用基础长度
        }

        scb->wcb.payload_len = payload_len; // 更新总长度

        // 根据掩码标志进入下一状态
        scb->status = scb->wcb.MASK ? CO_SOCKET_WEBSOCKET_MASK : CO_SOCKET_WEBSOCKET_PAYLOAD;
    }

    // 状态：读取掩码
    if (scb->status == CO_SOCKET_WEBSOCKET_MASK) {
        if (scb->remaining_len < scb->read_len + 4)
            return CO_OK; // 数据不足
        // 拷贝4字节掩码
        memcpy(&scb->wcb.mask.data[0], &data[scb->read_len], 4);
        scb->read_len += 4;
        scb->status = CO_SOCKET_WEBSOCKET_PAYLOAD; // 进入载荷读取状态
    } else {
        scb->status = CO_SOCKET_WEBSOCKET_PAYLOAD; // 直接进入载荷读取状态
    }

    return CO_OK; // 处理成功
}

// 发送WebSocket帧（假设载荷长度≤65535）
static co_err_t co_websocket_send_frame(void *frame_buffer, size_t payload_len, int frame_type)
{
    int sz;
    uint16_t payload_length;
    uint8_t *p;

    payload_length = payload_len;                                        // 记录载荷长度
    sz = co_websocket_get_res_payload_offset(payload_len) + payload_len; // 计算总帧大小

    p = frame_buffer; // 指向帧缓冲区
    // 构造帧头
    *p++ = WS_FIN | frame_type;                            // 设置FIN位和操作码
    *p++ = (payload_length >= 126 ? 126 : payload_length); // 设置长度标识

    // 处理扩展长度
    if (payload_length >= 126) {
        payload_length = htons(payload_length); // 转为网络字节序
        memcpy(p, &payload_length, 2);          // 写入扩展长度
        p += 2;
    }

    // 无掩码直接发送
    send(global_cb->websocket->fd, frame_buffer, sz, 0);
    return CO_OK; // 发送成功
}

// 构造并发送带状态码的文本消息
static co_err_t co_websocket_send_msg_with_code(int code, const char *msg)
{
    char *buffer;
    int len, ret;
    int offset;

    len = strlen(msg);                                 // 计算消息长度
    offset = co_websocket_get_res_payload_offset(len); // 计算帧头偏移
    buffer = malloc(offset + len + 25);                // 分配内存（含额外空间）
    if (buffer == NULL)
        return CO_ERROR_NO_MEM; // 内存分配失败

    // 格式化消息内容
    if (code == CO_RES_SUCCESS) {
        ret = snprintf(buffer + offset, len + 24, "code=%d&data=\"%s\"", code, msg); // 成功响应格式
    } else {
        ret = snprintf(buffer + offset, len + 24, "code=%d&data=\"msg=%s\"", code, msg); // 错误响应格式
    }

    if (ret < 0) {
        free(buffer);                // 释放内存
        return CO_ERROR_INVALID_ARG; // 格式化失败
    }

    // 发送文本帧
    ret = co_websocket_send_frame(buffer, ret, WS_OPCODE_TEXT);
    free(buffer); // 释放内存
    return ret;   // 返回发送结果
}

#if (CO_TEST_MODE == 1)
// 测试模式：回声功能
static co_err_t co_websocket_send_echo(void *data, size_t len, int frame_type)
{
    char *buffer;
    int ret;
    int offset = co_websocket_get_res_payload_offset(len); // 计算帧头偏移
    buffer = malloc(offset + len);                         // 分配内存
    if (!buffer)
        return CO_ERROR_NO_MEM;                             // 内存分配失败
    memcpy(buffer + offset, data, len);                     // 复制载荷数据
    ret = co_websocket_send_frame(buffer, len, frame_type); // 发送帧
    free(buffer);                                           // 释放内存
    return ret;                                             // 返回发送结果
}
#endif // (CO_TEST_MODE == 1)

// 处理二进制帧（转发给DAP）
static void co_websocket_process_binary(uint8_t *data, size_t len)
{
    co_websocket_process_dap(data, len); // 调用DAP处理函数
}

// 处理文本帧（暂未实现）
static void co_websocket_process_text(uint8_t *data, size_t len)
{
    // TODO: 实现文本帧处理逻辑
}

// 处理Ping帧（回复Pong）
static void co_websocket_process_ping(co_cb_t *cb, co_socket_cb_t *scb)
{
    int len = 2 + scb->wcb.payload_len + (scb->wcb.MASK ? 4 : 0); // 计算帧总长度
    scb->buf[0] = WS_FIN | WS_OPCODE_PONG;                        // 修改为Pong帧头
    send(scb->fd, scb->buf, len, 0);                              // 原样发回（含载荷）
}

// 处理关闭帧（发送关闭确认）
static void co_websocket_process_close(co_cb_t *cb, co_socket_cb_t *scb)
{
    uint8_t buf[4] = {
        WS_FIN | WS_OPCODE_CLOSE, // 关闭帧头
        0x02,                     // 长度标识（2字节状态码）
        0x03, 0xe8                // 状态码1000（正常关闭）
    };
    send(scb->fd, buf, 4, 0); // 发送关闭确认帧
}

// 循环右移32位
static inline CO_INLINE uint32_t co_rotr32(uint32_t n, unsigned int c)
{
    const unsigned int mask = (CHAR_BIT * sizeof(n) - 1); // 计算掩码
    c &= mask;                                            // 确保移位次数在合理范围内
    return (n >> c) | (n << ((-c) & mask));               // 实现循环右移
}

/**
 * @brief 快速WebSocket掩码处理（优化性能）
 * @param data 数据指针
 * @param mask 32位掩码（小端序）
 * @param len 数据长度
 */
static void co_websocket_fast_mask(uint8_t *data, uint32_t mask, size_t len)
{
    uint32_t new_mask;
    int align_len;
    size_t i;
    const uint8_t *p_mask = (uint8_t *)&mask; // 掩码字节指针
    unsigned long int dst = (long int)data;   // 目标地址

    // 长度≥8时使用字对齐优化
    if (len >= 8) {
        // 对齐地址
        align_len = (-dst) % 4; // 计算需要跳过的字节数
        len -= align_len;       // 调整剩余长度

        // 处理非对齐部分
        for (i = 0; i < align_len; i++) {
            data[i] ^= p_mask[i]; // 逐字节异或
        }

        // 计算新掩码（循环移位）
        switch (align_len) {
            case 1:
                new_mask = co_rotr32(mask, 8U); // 循环右移8位
                break;
            case 2:
                new_mask = co_rotr32(mask, 16U); // 循环右移16位
                break;
            case 3:
                new_mask = co_rotr32(mask, 24U); // 循环右移24位
                break;
            default:
                new_mask = mask; // 不移位
                break;
        }

        dst += align_len;              // 更新目标地址
        p_mask = (uint8_t *)&new_mask; // 更新掩码指针

        // 字对齐处理（每次4字节）
        for (i = 0; i < len / 4; i++) {
            *((uint32_t *)dst) ^= new_mask; // 4字节异或
            dst += 4;                       // 移动指针
        }

        len %= 4; // 计算剩余字节数
    }

    // 处理剩余字节
    for (i = 0; i < len; i++) {
        *((uint8_t *)dst) ^= p_mask[i % 4]; // 逐字节异或
        dst += 1;                           // 移动指针
    }
}

// 根据已处理长度更新掩码
static inline uint32_t co_websocket_get_new_mask(uint32_t mask, size_t len)
{
    switch (len & 0b11) { // 根据长度低2位决定移位量
        case 1:
            return co_rotr32(mask, 8U); // 循环右移8位
        case 2:
            return co_rotr32(mask, 16U); // 循环右移16位
        case 3:
            return co_rotr32(mask, 24U); // 循环右移24位
        default:
            return mask; // 不移位
    }
}

/**
 * @brief 处理WebSocket有效载荷
 * @return co_err_t
 *   - CO_OK: 处理完成
 *   - CO_ERROR_IO_PENDING: 还有后续帧待处理
 */
static co_err_t co_websocket_process_payload(co_cb_t *cb, co_socket_cb_t *scb)
{
    int len = min(scb->remaining_len - scb->read_len, scb->wcb.payload_len); // 计算本次处理长度
    uint8_t *data = (uint8_t *)scb->buf + scb->read_len;                     // 获取数据指针

    // 应用掩码（Ping帧除外）
    if (scb->wcb.MASK && scb->wcb.OPCODE != WS_OPCODE_PING) {
        uint32_t mask = scb->wcb.mask.val;                        // 获取掩码值
        co_websocket_fast_mask(data, mask, len);                  // 解除掩码
        scb->wcb.mask.val = co_websocket_get_new_mask(mask, len); // 更新掩码
    }

    // 根据操作码处理载荷
    switch (scb->wcb.OPCODE) {
        case WS_OPCODE_TEXT: // 文本帧
#if CO_TEST_MODE
            co_websocket_send_echo(data, len, WS_OPCODE_TEXT); // 测试模式回声
            break;
#endif
            // 跳过超长帧
            if (scb->wcb.skip_frame) {
                if (len == scb->wcb.payload_len)
                    scb->wcb.skip_frame = false; // 到达帧尾，重置标志
                break;
            }

            // 处理完整/分片文本帧
            if (len == scb->wcb.payload_len && !cb->recv_data_offset) {
                co_websocket_process_text(data, len); // 处理完整帧
            } else if (len > CONFIG_CO_WS_TEXT_BUFFER_SIZE - cb->recv_data_offset) {
                if (len < scb->wcb.payload_len)
                    scb->wcb.skip_frame = true;                                           // 标记跳过剩余帧
                co_websocket_send_msg_with_code(CO_RES_INVALID_SIZE, "request too long"); // 发送错误响应
                cb->recv_data_offset = 0;                                                 // 重置接收偏移
            } else {
                // 分片帧：拼接数据
                memcpy(cb->recv_data + cb->recv_data_offset, data, len); // 复制数据
                cb->recv_data_offset += len;                             // 更新偏移
                // 收到最后分片
                if (len == scb->wcb.payload_len) {
                    co_websocket_process_text(cb->recv_data, cb->recv_data_offset); // 处理完整数据
                    cb->recv_data_offset = 0;                                       // 重置偏移
                }
            }
            break;

        case WS_OPCODE_BINARY: // 二进制帧
#if CO_TEST_MODE
            co_websocket_send_echo(data, len, WS_OPCODE_BINARY); // 测试回声
            break;
#endif
            co_websocket_process_binary(data, len); // 处理DAP命令
            break;

        case WS_OPCODE_PING:                    // Ping帧
            co_websocket_process_ping(cb, scb); // 回复Pong
            break;

        case WS_OPCODE_PONG: // Pong帧（无操作）
            break;

        case WS_OPCODE_CLOSE:                    // 关闭帧
            co_websocket_process_close(cb, scb); // 处理关闭
            return CO_FAIL;                      // 触发关闭流程

        default:
            ESP_LOGE(CO_TAG, "unknow opcode: %d", scb->wcb.OPCODE); // 未知操作码错误
            break;
    }

    // 处理缓冲区剩余数据
    int new_len = scb->remaining_len - scb->read_len - len; // 计算剩余数据长度
    if (new_len > 0) {                                      // 存在未处理数据（新帧）
        memcpy(scb->buf, data + len, new_len);              // 移动数据到缓冲区头部
        scb->read_len = 0;                                  // 重置已读长度
        scb->remaining_len = new_len;                       // 更新剩余长度
        scb->status = CO_SOCKET_WEBSOCKET_HEADER;           // 回到帧头状态
        scb->wcb.payload_len = 0;                           // 重置载荷长度
        scb->wcb.payload_read_len = 0;                      // 重置已读载荷长度
        return CO_ERROR_IO_PENDING;                         // 需要继续处理
    } else if (scb->wcb.payload_len > len) {                // 载荷未读完
        scb->wcb.payload_len -= len;                        // 更新剩余载荷长度
        scb->read_len = 0;                                  // 重置已读长度
        scb->remaining_len = 0;                             // 重置剩余长度
        return CO_OK;                                       // 处理成功
    } else {                                                // 帧处理完成
        scb->read_len = 0;                                  // 重置已读长度
        scb->remaining_len = 0;                             // 重置剩余长度
        scb->status = CO_SOCKET_WEBSOCKET_HEADER;           // 准备下一帧
        scb->wcb.payload_len = 0;                           // 重置载荷长度
        scb->wcb.payload_read_len = 0;                      // 重置已读载荷长度
        return CO_OK;                                       // 处理成功
    }
}

// WebSocket 主处理函数
static esp_err_t co_websocket_process(co_cb_t *cb, co_socket_cb_t *scb)
{
    if (cb->websocket != scb)
        return ESP_FAIL; // 非当前WebSocket连接

    int fd = scb->fd, ret, offset = scb->remaining_len;
    // 接收数据
    ret = recv(fd, scb->buf + offset, CONFIG_CO_SOCKET_BUFFER_SIZE - offset, 0);
    if (ret <= 0)
        return ESP_FAIL;       // 接收错误
    scb->remaining_len += ret; // 更新剩余长度

    do {
        // 处理帧头（如果不在载荷状态）
        if (scb->status != CO_SOCKET_WEBSOCKET_PAYLOAD) {
            if (co_websocket_process_header(cb, scb) != CO_OK)
                return ESP_FAIL; // 处理失败
        }
        // 处理载荷
        if (scb->status == CO_SOCKET_WEBSOCKET_PAYLOAD) {
            ret = co_websocket_process_payload(cb, scb);
            if (ret == CO_FAIL)
                return ESP_FAIL; // 关闭帧触发
        }
    } while (ret == CO_ERROR_IO_PENDING); // 持续处理直到无新帧

    return ESP_OK; // 处理成功
}

/**
 * @brief 在HTTP头中查找字段值
 * @return 字段值起始位置（找不到返回NULL）
 */
static const char *co_http_header_find_field_value(
    const char *header_start, // 头起始位置
    const char *header_end,   // 头结束位置
    const char *field_name,   // 字段名
    const char *value         // 查找的具体值（可选）
)
{
    const char *field_start, *field_end, *next_crlf, *value_start;
    int field_name_len = strlen(field_name); // 计算字段名长度

    // 搜索字段名（跳过首部）
    field_start = header_start;
    do {
        field_start = strcasestr(field_start + 1, field_name); // 不区分大小写查找
        if (!field_start)
            break;                                    // 未找到
        field_end = field_start + field_name_len - 1; // 字段名结束位置

        // 检查字段名前是"\r\n"
        if (field_start - header_start >= 2 &&
            field_start[-2] == '\r' &&
            field_start[-1] == '\n' &&
            field_end[1] == ':')
            break; // 找到合法字段
    } while (1);

    if (!field_start)
        return NULL; // 未找到字段

    // 查找字段结束位置（"\r\n"）
    next_crlf = strcasestr(field_start, "\r\n");
    if (!next_crlf)
        return NULL; // 格式错误

    // 不指定具体值：返回整个字段值
    if (!value)
        return field_end + 2; // 跳过": "返回字段值

    // 查找具体值
    value_start = strcasestr(field_start, value);
    if (!value_start || value_start > next_crlf)
        return NULL; // 未找到值

    // 检查值边界（前后需为非字母数字）
    if (isalnum(value_start[-1]) || isalnum(value_start[strlen(value)]))
        return NULL; // 值边界不合法

    return value_start; // 返回找到的值位置
}

// 发送HTTP 400错误响应
static void co_http_error_400_response(co_cb_t *cb, co_socket_cb_t *scb)
{
    const char *error = "HTTP/1.1 400 Bad Request\r\n\r\n"; // 400错误响应
    send(scb->fd, error, strlen(error), 0);                 // 发送响应
}

// WebSocket GUID（RFC 6455）
#define WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" // WebSocket协议GUID

// SHA1封装
static int co_sha1(const unsigned char *src, size_t src_len, unsigned char *dst)
{
    return mbedtls_sha1_ret(src, src_len, dst); // 调用mbedTLS SHA1计算
}

// Base64编码封装
static int co_base64_encode(unsigned char *dst, size_t dst_len, size_t *written_len,
                            unsigned char *src, size_t src_len)
{
    return mbedtls_base64_encode(dst, dst_len, written_len, src, src_len); // 调用mbedTLS Base64编码
}

// 生成WebSocket Accept Key
static esp_err_t co_websocket_create_accept_key(char *dst, size_t dst_len, const char *client_key)
{
    uint8_t sha1buf[20]; // SHA1结果缓冲区
    char key_src[60];    // client_key(24) + GUID(36)

    memcpy(key_src, client_key, 24);   // 复制客户端Key
    memcpy(key_src + 24, WS_GUID, 36); // 复制GUID

    if (co_sha1((uint8_t *)key_src, 60, sha1buf) != 0)
        return ESP_FAIL; // SHA1计算失败

    size_t base64_encode_len;
    if (co_base64_encode((uint8_t *)dst, dst_len, &base64_encode_len, sha1buf, 20) != 0) {
        return ESP_FAIL; // Base64编码失败
    }
    dst[base64_encode_len] = '\0'; // 添加终止符
    return ESP_OK;                 // 成功
}

// 发送WebSocket握手响应
static esp_err_t co_websocket_handshake_send_key(int fd, const char *client_key)
{
    char res_header[256], accept_key[29]; // 响应头和Accept Key缓冲区
    if (co_websocket_create_accept_key(accept_key, sizeof(accept_key), client_key) != ESP_OK) {
        return ESP_FAIL; // 生成Accept Key失败
    }

    // 构造响应头
    int len = snprintf(res_header, sizeof(res_header),
                       "HTTP/1.1 101 Switching Protocols\r\n"
                       "Server: corsacOTA server\r\n"
                       "Upgrade: websocket\r\n"
                       "Connection: Upgrade\r\n"
                       "Sec-WebSocket-Accept: %s\r\n"
                       "\r\n",
                       accept_key);

    send(fd, res_header, len, 0); // 发送响应头
    return ESP_OK;                // 成功
}

// 处理WebSocket握手
static esp_err_t co_websocket_handshake_process(co_cb_t *cb, co_socket_cb_t *scb)
{
    if (scb->remaining_len == 0)
        memset(scb->buf, 0, CONFIG_CO_SOCKET_BUFFER_SIZE); // 清空缓冲区

    int fd = scb->fd, offset = scb->remaining_len;
    int ret = recv(fd, scb->buf + offset, CONFIG_CO_SOCKET_BUFFER_SIZE - offset, 0); // 接收数据
    if (ret <= 0) {
        co_http_error_400_response(cb, scb); // 接收失败，发送400错误
        return ESP_FAIL;
    }
    scb->remaining_len += ret; // 更新剩余长度

    // 检查是否收到完整HTTP头（以"\r\n\r\n"结束）
    if (scb->remaining_len < 4 || memcmp(scb->buf + scb->remaining_len - 4, "\r\n\r\n", 4) != 0) {
        return ESP_OK; // 头不完整，继续接收
    }

    const char *header_start = scb->buf, *header_end = scb->buf + scb->remaining_len - 1;
    const char *ws_key_start, *ws_key_end;

    // 验证必需字段
    if (!co_http_header_find_field_value(header_start, header_end, "Upgrade", "websocket") ||
        !co_http_header_find_field_value(header_start, header_end, "Connection", "Upgrade") ||
        !(ws_key_start = co_http_header_find_field_value(header_start, header_end, "Sec-WebSocket-Key", NULL))) {
        co_http_error_400_response(cb, scb); // 字段验证失败，发送400错误
        return ESP_FAIL;
    }

    // 跳过空格
    while (*ws_key_start == ' ')
        ws_key_start++;
    // 定位Key结束位置
    for (ws_key_end = ws_key_start; *ws_key_end != '\r' && *ws_key_end != ' '; ws_key_end++)
        ;

    // Key长度必须为24
    if (ws_key_end - ws_key_start != 24) {
        co_http_error_400_response(cb, scb); // Key长度非法，发送400错误
        return ESP_FAIL;
    }

    // 发送握手响应
    if (co_websocket_handshake_send_key(fd, ws_key_start) != ESP_OK) {
        co_http_error_400_response(cb, scb); // 发送响应失败
        return ESP_FAIL;
    }

    // 握手成功，状态转换
    ESP_LOGD(CO_TAG, "websocket handshake success");   // 记录日志
    cb->websocket = scb;                               // 记录有效连接
    scb->status = CO_SOCKET_WEBSOCKET_HEADER;          // 进入WebSocket模式
    scb->remaining_len = 0;                            // 重置缓冲区
    memset(scb->buf, 0, CONFIG_CO_SOCKET_BUFFER_SIZE); // 清空缓冲区
    return ESP_OK;                                     // 成功
}

// 分配DAP处理缓冲区（释放环形缓冲区）
static void websocket_buffer_malloc()
{
    if (ws_process_buffer)
        return;                       // 已分配则直接返回
    free_dap_ringbuf();               // 释放旧资源
    ws_process_buffer = malloc(1200); // 分配新缓冲区
}

// 释放DAP缓冲区
static void websocket_buffer_free()
{
    if (ws_process_buffer) {
        free(ws_process_buffer);  // 释放内存
        ws_process_buffer = NULL; // 重置指针
    }
}

// 处理DAP命令并回送响应
static void co_websocket_process_dap(uint8_t *data, size_t len)
{
    uint8_t *buf;
    int max_offset = co_websocket_get_res_payload_offset(1500); // 计算帧头偏移
    buf = ws_process_buffer + max_offset;                       // 定位载荷位置

    // 执行DAP命令（结果存入buf）
    int res = DAP_ExecuteCommand(data, buf) & 0xFFFF; // 执行命令并获取结果长度

    // 构造响应帧
    int offset = co_websocket_get_res_payload_offset(res); // 计算帧头偏移
    buf -= offset;                                         // 回退到帧头位置
    co_websocket_send_frame(buf, res, WS_OPCODE_BINARY);   // 发送二进制帧
}

// WebSocket工作线程入口
int websocket_worker(int fd, uint8_t *base, uint32_t length)
{
    co_cb_t cb = { 0 }; // 初始化控制块
    co_socket_cb_t scb = { 0 };
    cb.websocket = &scb;              // 关联套接字
    scb.fd = fd;                      // 设置套接字FD
    scb.status = CO_SOCKET_HANDSHAKE; // 初始状态：握手
    scb.buf = (char *)base;           // 使用传入的缓冲区
    scb.remaining_len = 4;            // 已读4字节（假设）

    global_cb = &cb; // 设置全局指针

    // 握手阶段
    esp_err_t ret;
    do {
        ret = co_websocket_handshake_process(&cb, &scb); // 处理握手
        if (ret != ESP_OK)
            return ret; // 握手失败
    } while (scb.status == CO_SOCKET_HANDSHAKE); // 循环直到握手完成

    websocket_buffer_malloc(); // 准备DAP缓冲区

    // WebSocket数据处理循环
    do {
        ret = co_websocket_process(&cb, &scb); // 处理WebSocket数据
        if (ret != ESP_OK)
            break; // 处理失败
    } while (1);

out:
    websocket_buffer_free(); // 清理资源
    return 0;                // 返回
}

#endif                                                         /* CONFIG_USE_WEBSOCKET_DAP*/